<?php

  require_once 'JooS/File.php';

  abstract class JooS_File_JAS extends JooS_File {
    const containerFolder = "jas";

    const exceptionCode_Forbidden = 403;
    const exceptionCode_NotFound = 404;
    const exceptionCode_NotEmplemented = 503;

    public static function getOriginalExt() {
      self::throwException("Not Emplemented (getOriginalExt)", self::exceptionCode_NotEmplemented);
    }

    abstract public function getContentType();

    abstract public function getJASFolder();

    abstract public function getMinifiedContent($value);

    abstract public function getUCS2($value);

    public static function getContent($jasFile) {
      $Content = null;
      try {
        $Ext = self::getFileExt($jasFile);

        require_once 'JooS/File/CSS.php';
        require_once 'JooS/File/JavaScript.php';

        switch ($Ext) {
          case JooS_File_CSS::getOriginalExt():
            $JAS = new JooS_File_CSS($jasFile);
            break;
          case JooS_File_JavaScript::getOriginalExt():
            $JAS = new JooS_File_JavaScript($jasFile);
            break;
          default:
            self::throwException("Bad file extention: [$jasFile]", self::exceptionCode_NotEmplemented);
        }

        $Files = explode(";", $jasFile);
        for ($i=0; $i<sizeof($Files); $i++) {
          if (substr($Files[$i], 0, 1) == "/" || substr($Files[$i], 0, 1) == "\\" || substr($Files[$i], 0, 1) == ".")
            self::throwException("Bad filename: [$jasFile]", self::exceptionCode_Forbidden);

          if (substr($Files[$i], -strlen($Ext), strlen($Ext)) !== $Ext)
            self::throwException("Bad filename: [$jasFile]", self::exceptionCode_Forbidden);
  
          $Files[$i] = str_replace(",", DIRECTORY_SEPARATOR, $Files[$i]);
          $Files[$i] = str_replace("\\", DIRECTORY_SEPARATOR, $Files[$i]);
          $Files[$i] = str_replace("/", DIRECTORY_SEPARATOR, $Files[$i]);
        }

        $Content = $JAS->getJASContent($Files);
      }
      catch (JooS_File_Exception $e) {
        require_once 'JooS/File/Content.php';

        $Content = new JooS_File_Content();
        $Content->setError($e);
      }
      return $Content;
    }

    private $Content = null;
    
    protected function __construct() {
      parent::__construct();

      require_once 'JooS/File/Content.php';
      $this->Content = new JooS_File_Content($this->getContentType());
    }

    private static function getFileExt($jasFile) {
      $parts = explode(".", $jasFile);
      if (sizeof($parts) > 1)
        return array_pop($parts);
      else
        self::throwException("Bad filename: [$jasFile]", self::exceptionCode_Forbidden);
    }

    private function getJASContent($Files) {
      $base = self::containerFolder . DIRECTORY_SEPARATOR . $this->getJASFolder();

      $all_elements = array();
      $all_copyrights = array();
      $this->RequireAllFiles($base, $Files, $all_elements, $all_copyrights);

      foreach ($all_elements as $k=>$v)
        if (!$v)
          unset($all_elements[$k]);

      $value = implode("\n", $all_elements);
      foreach ($all_copyrights as $k=>$v)
        if (!$v)
          unset($all_copyrights[$k]);
      $copyrights = implode("", $all_copyrights);

      $this->Content->setValue($this->getMinifiedContent($value));
      $this->Content->setCopyrights($this->getUCS2($copyrights));

      return $this->Content;
    }
    
    private function RequireFile(&$base, $element, &$array, &$copyrights) {
      $element_path = $base . DIRECTORY_SEPARATOR . $element;

      if (!isset($array[$element_path])) {
        $array[$element_path] = false;

        $requiresName = $element_path.'.requires';
        $requiresFiles = parent::getContent($requiresName);
        if ($requiresFiles !== false) {
          $requiresFiles = explode("\n", $requiresFiles);

          $ex = explode(DIRECTORY_SEPARATOR, $element_path);
          array_pop($ex);
          $ex = implode(DIRECTORY_SEPARATOR, $ex);
          $this->RequireAllFiles($ex, $requiresFiles, $array, $copyrights);

          unset($array[$element_path]);
          $array[$element_path] = false;
        }
        $array[$element_path] = self::includeFile($element_path);

        $copyrightName = $element_path.'.copyright';
        $copyrightContent = parent::getContent($copyrightName);
        if ($copyrightContent !== false)
          $copyrights[$copyrightName] = $copyrightContent;
      }
    }

    private function RequireAllFiles(&$base, $files, &$array, &$copyrights) {
      if (is_array($files)) {
        reset($files);
        while (list(,$element) = each($files)) {
          if ($element = trim($element)) {
            $element = str_replace("\\", DIRECTORY_SEPARATOR, str_replace("/", DIRECTORY_SEPARATOR, $element));
            $this->RequireFile($base, $element, $array, $copyrights);
          }
        }
      }
    }
  }

?>